package edu.dublbo.app.generator.service;

import edu.dublbo.app.generator.entity.TBasicModel;
import edu.dublbo.app.generator.entity.TBasicModelDetail;
import edu.dublbo.app.generator.mapper.TBasicModelDetailMapper;
import edu.dublbo.app.generator.mapper.TBasicModelMapper;
import edu.dublbo.app.generator.result.OptStatus;
import edu.dublbo.app.generator.result.PageResult;
import edu.dublbo.app.generator.result.Result;
import edu.dublbo.app.generator.util.Constant;
import edu.dublbo.app.generator.util.DemoUtils;
import edu.dublbo.app.generator.util.SnowflakeIdWorker;
import edu.dublbo.app.generator.util.StrUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author DubLBo
 * @since 2020-09-05 16:56
 * i believe i can i do
 */
@Service
public class BasicModelService {
    private static final Logger logger = LoggerFactory.getLogger(BasicModelService.class);

    @Resource
    private TBasicModelMapper mapper;
    @Resource
    private SnowflakeIdWorker idWorker;
    @Resource
    private TBasicModelDetailMapper modelDetailMapper;

    public List<TBasicModel> list(Map<String, Object> condition) {
        return mapper.select(condition);
    }

    public TBasicModel get(String id) {
        return mapper.get(id);
    }

    @Transactional
    public Result<Object> saveOrUpdate(TBasicModel entity) {
        logger.info("add or update model: {}", entity);

        if (!TBasicModel.checkValid(entity)) {
            return Result.builder().code(OptStatus.FAIL.code).msg("数据不合法").build();
        }

        // 生成表名
        String tableName = DemoUtils.modelName2TableName(entity.getModelName());
        if (StrUtils.isEmpty(tableName)) {
            return Result.builder()
                    .code(OptStatus.FAIL.code)
                    .msg("生成表名错误，请稍后重试")
                    .build();
        }

        String busiName = DemoUtils.genBusiBeanName(entity.getModelName());
        if (StrUtils.isEmpty(busiName)) {
            return Result.builder()
                    .code(OptStatus.FAIL.code)
                    .msg("生成业务类名错误，请稍后检查实体类名是否输入正确")
                    .build();
        }
//        entity
        entity.setTableName(tableName);
//        entity.generateSomeInfo();

        // 判断实体类是否重复（包名 + 模型名）
        Map<String, Object> map = new HashMap<>();
        map.put("modelName", entity.getModelName());
        map.put("xid", entity.getId());
        Long cnt = mapper.selectCount(map);
        if (cnt != null && cnt > 0) {
            return Result.builder()
                    .code(OptStatus.FAIL.code)
                    .msg("实体类重复，请重新输入")
                    .build();
        }

        if (StrUtils.isEmpty(entity.getId())) {
            // add
            // 添加模型
            Date now = new Date();
            String mId = idWorker.nextStringId();
            entity.setId(mId);
            entity.setCreateUser(Constant.CURRENT_USER);
            entity.setCreateTime(now);
            entity.setModifyUser(Constant.CURRENT_USER);
            entity.setModifyTime(now);
            entity.setDeleteFlag(Constant.LOGIC_NOT_DELETE_VAL);
            mapper.add(entity);

            // 添加默认的字段
            List<TBasicModelDetail> details = new ArrayList<>();
            now = new Date();
            DemoUtils.DEFAULT_PROS.get(0).setModelId(mId);
            DemoUtils.DEFAULT_PROS.get(0).setId(idWorker.nextStringId());
            DemoUtils.DEFAULT_PROS.get(0).setCreateTime(now);
            DemoUtils.DEFAULT_PROS.get(0).setModifyTime(now);
            DemoUtils.DEFAULT_PROS.get(0).setDeleteFlag(Constant.LOGIC_NOT_DELETE_VAL);
            details.add(DemoUtils.DEFAULT_PROS.get(0));
            int sz = DemoUtils.DEFAULT_PROS.size();
            if (entity.getDefProNos() != null) {
                for(int i : entity.getDefProNos()) {
                    if (i > 0 && i < sz) {
                        TBasicModelDetail o = DemoUtils.DEFAULT_PROS.get(i);
                        o.setModelId(mId);
                        o.setId(idWorker.nextStringId());
                        o.setCreateTime(now);
                        o.setModifyTime(now);
                        o.setDeleteFlag(Constant.LOGIC_NOT_DELETE_VAL);
                        details.add(o);
                    }
                }
            }
            modelDetailMapper.batchAdd(details);
            return Result.builder().code(OptStatus.SUCCESS.code).build();
        } else {
            // update
            entity.setModifyUser(Constant.CURRENT_USER);
            entity.setModifyTime(new Date());
            mapper.update(entity);
            return Result.builder().code(OptStatus.SUCCESS.code).build();
        }
    }

    public PageResult<TBasicModel> listPage(int pageNo, int pageSize, String searchTxt, String of, String ot) {
        Map<String, Object> con = new HashMap<>();

        if (!StrUtils.isBlank(searchTxt)) {
            con.put("searchTxt", searchTxt);
        }

        Long count = mapper.selectCount(con);
        long total = count == null ? 0L : count;
        if (total < 1)
            return PageResult.<TBasicModel>builder()
                    .code(OptStatus.SUCCESS.code)
                    .build();

        if (StrUtils.isEmpty(of)) {
            con.put("_order", "modify_time");
            con.put("_sort", "DESC");
        } else {
            if (Constant.ORDER_DESC.equals(ot)) {
                con.put("_order", of);
                con.put("_sort", Constant.ORDER_DESC);
            } else if (Constant.ORDER_ASC.equals(ot)) {
                con.put("_order", of);
                con.put("_sort", Constant.ORDER_ASC);
            } else {
                con.put("_order", "modify_time");
                con.put("_sort", "DESC");
            }
        }

        pageNo = Math.max(1, pageNo);
        con.put("startNo", (pageNo - 1) * pageSize);
        con.put("pageSize", pageSize);
        List<TBasicModel> list = mapper.select(con);

        return PageResult.<TBasicModel>builder()
                .page(pageNo)
                .code(OptStatus.SUCCESS.code)
                .data(list)
                .count(total)
                .build();
    }


    @Transactional
    public Result<Object> deleteById(String modelId) {
        // 1. 删除模型下的所有模型明细
        // 2. 删除模型
        Date now = new Date();
        Map<String, Object> condition = new HashMap<>();
        condition.put("id", modelId);
        condition.put("modifyTime", now);
        condition.put("modifyUser", Constant.CURRENT_USER);
        condition.put("deleteFlag", Constant.LOGIC_DELETE_VAL);
        int cnt = mapper.updateByMap(condition);
        if (cnt > 0) {
            now = new Date();
            condition.remove("id");
            condition.put("modifyTime", now);
            condition.put("modelId", modelId);
            modelDetailMapper.batchUpdateDelete(condition);
        }

        return Result.builder().code(OptStatus.SUCCESS.code).build();
    }

//    @Transactional
//    public List<TBasicModel> listAll() {
//        return mapper.listAll();
//    }


}
